//----------------------------------------------------------------------------
// util.cpp
//
// utility functions for swine
//
// Copyright (C) 2011 Neil Butterworth
//----------------------------------------------------------------------------

#include "util.h"
#include "error.h"

using std::string;
using std::istream;

namespace Swine {

//----------------------------------------------------------------------------
// The reply sent back to the calling script.  Always wriiten to std::out.
//----------------------------------------------------------------------------

void Reply( const std::string & s ) {
	std::cout << s << std::endl;
}

//----------------------------------------------------------------------------
// read iostream input into a string, terminating lines with newline
//----------------------------------------------------------------------------

string ReadLines( istream & is ) {
	string rv, line;
	while( getline( is, line ) ) {
		rv += line;
		rv += "\n";
	}
	return rv;
}

//----------------------------------------------------------------------------
// Translate icon name to Windows integer value
//----------------------------------------------------------------------------

struct IconName {
	const char * const mName;
	int mIcon;
};

static IconName IconNames[] = {
	{ "info", MB_ICONINFORMATION },
	{ "warn", MB_ICONWARNING },
	{ "stop", MB_ICONSTOP },
	{ "query", MB_ICONQUESTION },
	{ 0, 0 }
};

int IconFromName( const string & iname ) {
	int i = 0;
	while( IconNames[i].mName ) {
		if ( iname == IconNames[i].mName ) {
			return IconNames[i].mIcon;
		}
		i++;
	}
	throw Error( "Invalid icon name: " + iname );
}




//----------------------------------------------------------------------------
// As above, but for buttons
//----------------------------------------------------------------------------

struct ButtonName {
	const char * const mName;
	int mButton;
};

static ButtonName ButtonNames[] = {
	{ "yesno", MB_YESNO },
	{ "okcancel", MB_OKCANCEL },
	{ "yesnocancel", MB_YESNOCANCEL },
	{ "retrycancel", MB_RETRYCANCEL },
	{ 0, 0 }
};

int ButtonsFromName( const string & bname ) {
	int i = 0;
	while( ButtonNames[i].mName ) {
		if ( bname == ButtonNames[i].mName ) {
			return ButtonNames[i].mButton;
		}
		i++;
	}
	throw Error( "Invalid button name: " + bname );
}

//----------------------------------------------------------------------------

struct But2Name {
	const char * const mName;
	int mButt;
};

static But2Name ButtonValues[] = {
	{ "yes", IDYES },
	{ "no", IDNO },
	{ "ok", IDOK },
	{ "cancel", IDCANCEL },
	{ "retry", IDRETRY },
	{ 0, 0 }
};

string ButtonToString( int butt ) {
	int i = 0;
	while( ButtonValues[i].mName ) {
		if ( ButtonValues[i].mButt == butt ) {
			return ButtonValues[i].mName;
		}
		i++;
	}
	throw Error( "Unsupported button value:" );
}

//----------------------------------------------------------------------------
// Get text from control in a dialog
//----------------------------------------------------------------------------

string TextFromCtrl( HWND parent, int ctrl ) {
	HWND hc = GetDlgItem( parent, ctrl );
	int n = GetWindowTextLength( hc ) + 1;
	string s( n, 0 );
	GetWindowText( hc, &s[0], n );
	return s;
}

//----------------------------------------------------------------------------
// Set text of control
//----------------------------------------------------------------------------

void SetCtrlText( HWND parent, int id, const string & text ) {
	HWND hc = MustGetControl( parent, id );
	SendMessage( hc, WM_SETTEXT, 0, (LPARAM) text.c_str() );
}

//----------------------------------------------------------------------------
// Set focus to specified control in dialog
//----------------------------------------------------------------------------

void SetFocus( HWND parent, int id ) {
	::SetFocus( MustGetControl( parent, id) );
}

//----------------------------------------------------------------------------
// Get handle to control in dialog, or fail noisily
//----------------------------------------------------------------------------

HWND MustGetControl( HWND parent, int id ) {
	HWND ctrl = GetDlgItem( parent, id );
	if ( ctrl == 0 ) {
		throw Error( "Invalid control id: " + Str( id ) );
	}
	return ctrl;
}

//----------------------------------------------------------------------------
// Get selected text from listbox, or fail noisily
//----------------------------------------------------------------------------

string GetListBoxSelection( HWND parent, int lbid ) {
	HWND lb = MustGetControl( parent, lbid );
	int sel = SendMessage( lb, LB_GETCURSEL, 0, 0 );
	if ( sel == LB_ERR ) {
		throw Error( "Weirdo listbox selection index" );
	}
	int n = SendMessage( lb, LB_GETTEXTLEN, sel, 0 ) + 1;
	string s( n, 0 );
	SendMessage( lb, LB_GETTEXT, sel, (LPARAM) &s[0] );
	return s;
}

//----------------------------------------------------------------------------
// Get process id as string
//----------------------------------------------------------------------------

string GetPID() {
	DWORD pid = GetCurrentProcessId();
	return Str( pid );
}

//----------------------------------------------------------------------------
// Something of a hack to get window handle of specific process
//----------------------------------------------------------------------------

static string spid;

static BOOL CALLBACK EnumProc( HWND hwnd, LPARAM lParam  ) {
	DWORD pid;
	GetWindowThreadProcessId( hwnd, &pid );
	if ( Str( pid ) == spid ) {
		* (HWND *) lParam = hwnd;
		return FALSE;
	}
	else {
		return TRUE;
	}
}


HWND GetHwndFromPid( const std::string & pid ) {
	spid = pid;
	HWND hwnd = 0;
	EnumWindows( EnumProc, (LPARAM) & hwnd );
	return hwnd;
}

//----------------------------------------------------------------------------
// Initialise an open file name struct
//----------------------------------------------------------------------------

OPENFILENAME MakeOFS() {
	OPENFILENAME ofs;
	memset( &ofs, 0, sizeof(ofs) );
	ofs.lStructSize = sizeof( ofs );
	ofs.hwndOwner = 0;
	ofs.hInstance = GetModuleHandle( 0 );
	return ofs;
}


//----------------------------------------------------------------------------

} // namespace











